﻿using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using ERP.BLL.MenuApp;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;

namespace ERP.Web.Core.Authentication.JwtBearer
{
    public class TokenProviderMiddleware
    {
        private readonly TokenProviderOptions _options;
        private readonly IAuthenticationSchemeProvider _schemes;
        private readonly RequestDelegate _next;

        public TokenProviderMiddleware(
            TokenProviderOptions options,
            RequestDelegate next,
            IAuthenticationSchemeProvider schemes)
        {
            _options = options;
            _next = next;
            _schemes = schemes;
        }

        public async Task Invoke(HttpContext context)
        {
            //请求Url
            var questUrl = context.Request.Path.Value.ToLower();

            if (questUrl.Equals(_options.Path, StringComparison.Ordinal))
            {
                await _next(context);
                return;
            }

            var defaultAuthenticate = await _schemes.GetDefaultAuthenticateSchemeAsync();

            if (defaultAuthenticate != null)
            {
                var result = await context.AuthenticateAsync(defaultAuthenticate.Name);

                if (result.Failure != null)
                {
                    if (result.Failure.TargetSite.Name == "ValidateLifetime")
                    {
                        await ReturnBadRequest(context, 402);
                        return;
                    }
                }

                if (result.Principal != null)
                {
                    context.User = result.Principal;
                    if (context.User.Identity.Name == "admin")
                    {
                        await _next(context);
                        return;
                    }

                    var userRoleIds = context.User.Claims.Where(s => s.Type == ClaimTypes.Role).Select(t => t.Value);
                    var actionPermissions =
                        context.RequestServices.GetRequiredService<IMenuService>().GetRolesPermissions();
                    if (!actionPermissions.Any(w => userRoleIds.Contains(w.Name) && w.Url.ToLower() == questUrl))
                    {
                        await ReturnBadRequest(context, 401);
                        return;
                    }
                }
            }

            await _next(context);
        }

        private static async Task ReturnBadRequest(HttpContext context, int statusResult)
        {
            context.Response.StatusCode = 200;
            context.Response.ContentType = "application/json; charset=utf-8;";
            context.Response.Headers.Add("Access-Control-Allow-Origin", "http://47.106.191.56:8089");
            context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            await context.Response.WriteAsync(JsonConvert.SerializeObject(new
            {
                Result = statusResult
            }).ToLower());
        }
    }
}